//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "flash_bsp.h"
#include "gd32f4xx_crc.h"
#include "gd32f4xx_rcu.h"

/*输入扇区起始地址，获取所在的扇区编号*/
static unsigned int WHT_Flash_BSP_Get_Sector_number(WHT_Flash_Sector_Base_Address_enum sector_base_address)
{
    switch (sector_base_address)
    {
    case FLASH_Sector_0_Base_Address:return Flash_Sector_0;
    case FLASH_Sector_1_Base_Address:return Flash_Sector_1;
    case FLASH_Sector_2_Base_Address:return Flash_Sector_2;
    case FLASH_Sector_3_Base_Address:return Flash_Sector_3;
    case FLASH_Sector_4_Base_Address:return Flash_Sector_4;
    case FLASH_Sector_5_Base_Address:return Flash_Sector_5;
    case FLASH_Sector_6_Base_Address:return Flash_Sector_6;
    case FLASH_Sector_7_Base_Address:return Flash_Sector_7;
    case FLASH_Sector_8_Base_Address:return Flash_Sector_8;
    case FLASH_Sector_9_Base_Address:return Flash_Sector_9;
    case FLASH_Sector_10_Base_Address:return Flash_Sector_10;
    case FLASH_Sector_11_Base_Address:return Flash_Sector_11;
    case FLASH_Sector_12_Base_Address:return Flash_Sector_12;
    case FLASH_Sector_13_Base_Address:return Flash_Sector_13;
    case FLASH_Sector_14_Base_Address:return Flash_Sector_14;
    case FLASH_Sector_15_Base_Address:return Flash_Sector_15;
    case FLASH_Sector_16_Base_Address:return Flash_Sector_16;
    case FLASH_Sector_17_Base_Address:return Flash_Sector_17;
    case FLASH_Sector_18_Base_Address:return Flash_Sector_18;
    case FLASH_Sector_19_Base_Address:return Flash_Sector_19;
    case FLASH_Sector_20_Base_Address:return Flash_Sector_20;
    case FLASH_Sector_21_Base_Address:return Flash_Sector_21;
    case FLASH_Sector_22_Base_Address:return Flash_Sector_22;
    case FLASH_Sector_23_Base_Address:return Flash_Sector_23;
    case FLASH_Sector_24_Base_Address:return Flash_Sector_24;
    case FLASH_Sector_25_Base_Address:return Flash_Sector_25;
    case FLASH_Sector_26_Base_Address:return Flash_Sector_26;
    case FLASH_Sector_27_Base_Address:return Flash_Sector_27;
    default:return (unsigned int)-1;
    }
}
/*输入扇区编号，获取起始地址*/
static unsigned int WHT_Flash_BSP_Get_Sector_Addr(WHT_Flash_Sector_Number_enum sector_number)
{
    switch (sector_number)
    {
    case Flash_Sector_0:return FLASH_Sector_0_Base_Address;
    case Flash_Sector_1:return FLASH_Sector_1_Base_Address;
    case Flash_Sector_2:return FLASH_Sector_2_Base_Address;
    case Flash_Sector_3:return FLASH_Sector_3_Base_Address;
    case Flash_Sector_4:return FLASH_Sector_4_Base_Address;
    case Flash_Sector_5:return FLASH_Sector_5_Base_Address;
    case Flash_Sector_6:return FLASH_Sector_6_Base_Address;
    case Flash_Sector_7:return FLASH_Sector_7_Base_Address;
    case Flash_Sector_8:return FLASH_Sector_8_Base_Address;
    case Flash_Sector_9:return FLASH_Sector_9_Base_Address;
    case Flash_Sector_10:return FLASH_Sector_10_Base_Address;
    case Flash_Sector_11:return FLASH_Sector_11_Base_Address;
    case Flash_Sector_12:return FLASH_Sector_12_Base_Address;
    case Flash_Sector_13:return FLASH_Sector_13_Base_Address;
    case Flash_Sector_14:return FLASH_Sector_14_Base_Address;
    case Flash_Sector_15:return FLASH_Sector_15_Base_Address;
    case Flash_Sector_16:return FLASH_Sector_16_Base_Address;
    case Flash_Sector_17:return FLASH_Sector_17_Base_Address;
    case Flash_Sector_18:return FLASH_Sector_18_Base_Address;
    case Flash_Sector_19:return FLASH_Sector_19_Base_Address;
    case Flash_Sector_20:return FLASH_Sector_20_Base_Address;
    case Flash_Sector_21:return FLASH_Sector_21_Base_Address;
    case Flash_Sector_22:return FLASH_Sector_22_Base_Address;
    case Flash_Sector_23:return FLASH_Sector_23_Base_Address;
    case Flash_Sector_24:return FLASH_Sector_24_Base_Address;
    case Flash_Sector_25:return FLASH_Sector_25_Base_Address;
    case Flash_Sector_26:return FLASH_Sector_26_Base_Address;
    case Flash_Sector_27:return FLASH_Sector_27_Base_Address;
    default:return (unsigned int)-1;
    }
}


/*擦除扇区*/
ErrStatus WHT_Flash_BSP_Erase_And_Check(WHT_Flash_Sector_Number_enum start_sector_number, unsigned int sector_count)
{
    fmc_state_enum status = FMC_READY;
    WHT_Flash_Sector_Number_enum FLASH_Sector = start_sector_number;

    /*擦除*/
    fmc_unlock();//Flash解锁
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR | FMC_FLAG_RDDERR);//清空所有标志位
    for(unsigned char i = 0; i < sector_count; i++)//扇区擦除
    {
        #if defined(WWDG_FUNC_ENABLE)
        extern WHT_WWDG_Config_t WWDG_Config;
        WHT_WWDG_BSP.WHT_Reset_Start_Time(&WWDG_Config);
        #endif /*WWDG_FUNC_ENABLE*/
        status = fmc_sector_erase(FLASH_Sector);
        if (status != FMC_READY)
            break;
        if (FLASH_Sector == Flash_Sector_11)//扇区11到12特殊
            FLASH_Sector = Flash_Sector_12;
        else
            FLASH_Sector += 1 << 3;
	}
    fmc_lock();//Flash上锁

    /*查空*/
    if (status == FMC_READY)
    {
        unsigned int Flash_Start_Addr = WHT_Flash_BSP_Get_Sector_Addr(start_sector_number);
        unsigned int Flash_End_Addr = WHT_Flash_BSP_Get_Sector_Addr(FLASH_Sector);

        if (Flash_End_Addr == (unsigned int)-1)
        {
            Flash_End_Addr = WHT_Flash_BSP_Get_Sector_Addr(Flash_Sector_23) + 128 * 1024;
        }
        for (; Flash_Start_Addr <  Flash_End_Addr; Flash_Start_Addr += 4)
        {
            if (*((volatile unsigned int*)Flash_Start_Addr) != 0xffffffff)
            {
                status = FMC_OPERR;
                break;
            }
        }
    }
    return (status == FMC_READY ? SUCCESS : ERROR);
}
/*读取内部FLASH*/
void WHT_Flash_BSP_Read(unsigned int start_addr, unsigned char* out_buf, unsigned int size)
{
    unsigned int Word_Count = size / sizeof(unsigned int);
    unsigned char End_Count = size % sizeof(unsigned int);

    for (unsigned int i = 0; i < Word_Count; i++)
    {
        ((unsigned int*)out_buf)[i] = ((volatile unsigned int*)start_addr)[i];
    }
    while(End_Count--)
    {
        out_buf[size - End_Count] = *((volatile unsigned char*)(start_addr + size - End_Count));
    }
}
/*写入内部FLASH*/
ErrStatus WHT_Flash_BSP_Write(unsigned int start_addr, const unsigned char* in_buf, unsigned int size)
{
    fmc_state_enum status = FMC_READY;
    unsigned int Word_Count = size / sizeof(unsigned int);
    unsigned char End_Count = size % sizeof(unsigned int);

    /*烧录*/
    fmc_unlock();//Flash解锁   
    for (unsigned int i = 0; i < Word_Count; i++)
    {
        status = fmc_word_program(start_addr, ((const unsigned int*)in_buf)[i]);
        if (status != FMC_READY)
            break;
        start_addr += sizeof(unsigned int);
    }
    if (End_Count && (status == FMC_READY))
    {
        status = fmc_word_program(start_addr, ((unsigned int*)in_buf)[Word_Count] | (0xffffffff << (End_Count * 8)));///高位数据设置0xff
    }
    fmc_lock();//Flash上锁

    /*校验*/
    if (status == FMC_READY)
#if 1
    {//芯片自带CRC32校验，参与校验数据不全，4字节对齐
        unsigned int CRC32_Src;
        unsigned int CRC32_Dst;

        rcu_periph_clock_enable(RCU_CRC);
        crc_data_register_reset();
        CRC32_Src = crc_block_data_calculate((unsigned int*)in_buf, Word_Count);
        start_addr -= Word_Count * sizeof(unsigned int);
        crc_data_register_reset();
        CRC32_Dst = crc_block_data_calculate((unsigned int*)start_addr, Word_Count);
        if (CRC32_Src != CRC32_Dst)
            status = FMC_OPERR;
    }
#else
    {//手动全校验
        start_addr -= Word_Count * sizeof(unsigned int);
        for (unsigned int i = 0; i < size; i++)
        {
            if (((volatile unsigned char*)start_addr)[i] != in_buf[i])
            {
                status = FLASH_ERROR_PGP;
                break;
            }
        }
    }
#endif
    return (status == FMC_READY ? SUCCESS : ERROR);
}
